package model

import (
	"exercise/application/yiran/app/initialize"
	"github.com/go-redis/redis"
	"gorm.io/gorm"
)

// Paging 分页
type Paging struct {
	Page     int
	PageSize int
}

// OrderOrGroup 排序或分组
type OrderOrGroup struct {
	Order  string
	Group  string
	Having string
}

// TableAndJoin 链表查询
type TableAndJoin struct {
	TableName string
	Field     string
	Joins     []string
}

type db struct {
	dbname string
}

// Connect 获取操作的数据库
func (d *db) Connect() (b *gorm.DB) {
	switch d.dbname {
	default:
		b = initialize.YrDbConnect()
	}
	if b == nil {
		panic("数据库异常,未获取到数据库对象")
	}
	return
}

// FindOne 获取一条数据
func (d *db) FindOne(model interface{}, whereSql interface{}, where []interface{}, fields string, preload []string) (err error) {
	query := d.Connect()
	if fields == "" { //指定字段
		fields = "*"
	}

	query = query.Select(fields)

	if whereSql != nil && len(where) != 0 { //条件查询
		query = query.Where(whereSql, where...)
	}

	if preload != nil {
		for _, v := range preload {
			query.Preload(v)
		}
	}
	err = query.First(model).Error
	return
}

// FindOneMap 获取一条数据
func (d *db) FindOneMap(model interface{}, whereSql interface{}, where []interface{}, fields string, one *map[string]interface{}) (err error) {
	query := d.Connect()
	if fields == "" { //指定字段
		fields = "*"
	}

	query = query.Model(model).Select(fields)

	if whereSql != nil && len(where) != 0 { //条件查询
		query = query.Where(whereSql, where...)
	}

	err = query.First(one).Error
	return
}

// FindAll 查询全部
func (d *db) FindAll(model interface{}, whereSql interface{}, where []interface{}, orderOrGroup OrderOrGroup, paging Paging, preload []string) (err error) {
	query := d.Connect()
	if whereSql != nil && len(where) != 0 { //条件查询
		query = query.Where(whereSql, where...)
	}

	if orderOrGroup.Group != "" { //分组
		query = query.Group(orderOrGroup.Group)
		if orderOrGroup.Having != "" { //分组筛选
			query = query.Having(orderOrGroup.Having)
		}
	}

	if orderOrGroup.Order != "" { //排序
		query = query.Order(orderOrGroup.Order)
	}

	if paging.Page != 0 { //分页
		var pageSize int = 10
		if paging.PageSize != 0 {
			pageSize = paging.PageSize
		}
		query = query.Offset((paging.Page - 1) * pageSize).Limit(pageSize)
	}

	if preload != nil {
		for _, v := range preload {
			query.Preload(v)
		}
	}

	err = query.Find(model).Error
	return
}

// FindAllAndCount 获取列表和数量
func (d *db) FindAllAndCount(model interface{}, whereSql interface{}, where []interface{}, orderOrGroup OrderOrGroup, paging Paging, preload []string) (count int64, err error) {
	query := d.Connect()
	if whereSql != nil && len(where) != 0 { //条件查询
		query = query.Where(whereSql, where...)
	}

	if orderOrGroup.Group != "" { //分组
		query = query.Group(orderOrGroup.Group)
		if orderOrGroup.Having != "" { //分组筛选
			query = query.Having(orderOrGroup.Having)
		}
	}

	if orderOrGroup.Order != "" { //排序
		query = query.Order(orderOrGroup.Order)
	}

	//查询数量
	err = query.Model(model).Count(&count).Error

	if err != nil { //查询数量失败
		return count, err
	}

	if paging.Page != 0 { //分页
		var pageSize int = 10
		if paging.PageSize != 0 {
			pageSize = paging.PageSize
		}
		query = query.Offset((paging.Page - 1) * pageSize).Limit(pageSize)
	}

	if preload != nil {
		for _, v := range preload {
			query.Preload(v)
		}
	}

	//查询数据列表
	err = query.Find(model).Error

	return
}

// FindCount 统计数量
func (d *db) FindCount(model interface{}, whereSql interface{}, where []interface{}, orderOrGroup OrderOrGroup) (count int64, err error) {
	query := d.Connect()
	if whereSql != nil && len(where) != 0 { //条件查询
		query = query.Where(whereSql, where...)
	}

	if orderOrGroup.Group != "" { //分组
		query = query.Group(orderOrGroup.Group)
		if orderOrGroup.Having != "" { //分组筛选
			query = query.Having(orderOrGroup.Having)
		}
	}

	if orderOrGroup.Order != "" { //排序
		query = query.Order(orderOrGroup.Order)
	}

	err = query.Model(model).Count(&count).Error
	return
}

// InsertRecord 插入数据
func (d *db) InsertRecord(model interface{}) (err error) {
	err = d.Connect().Create(model).Error
	return
}

// BatchInsertRecord 批量插入
func (d *db) BatchInsertRecord(model interface{}, list []map[string]interface{}) (err error) {
	err = d.Connect().Model(model).Create(list).Error
	return err
}

// UpdateRecord 批量修改记录
func (d *db) UpdateRecord(model interface{}, whereSql interface{}, where []interface{}, update map[string]interface{}) (err error) {
	query := d.Connect().Model(model)
	if whereSql != nil && len(where) != 0 { //条件查询
		query = query.Where(whereSql, where...)
	}
	err = query.Updates(update).Error
	return
}

// DeleteRecord 删除记录
func (d *db) DeleteRecord(model interface{}, whereSql interface{}, where []interface{}) (err error) {
	query := d.Connect()
	if whereSql != nil && len(where) != 0 { //条件查询
		query = query.Where(whereSql, where...)
	}
	err = query.Delete(model).Error
	return
}

// SaveRecord 模型方式修改
func (d *db) SaveRecord(model interface{}) (err error) {
	err = d.Connect().Save(model).Error
	return err
}

// FindJoinAllAndCount join查询
func (d *db) FindJoinAllAndCount(tableAndJoin TableAndJoin, list interface{}, whereSql interface{}, where []interface{}, orderOrGroup OrderOrGroup, paging Paging) (count int64, err error) {
	if tableAndJoin.TableName == "" || tableAndJoin.Joins == nil {
		return count, err
	}
	query := d.Connect().Table(tableAndJoin.TableName)
	for _, v := range tableAndJoin.Joins {
		query.Joins(v)
	}

	field := tableAndJoin.Field
	if field == "" {
		field = "*"
	}

	query.Select(field)

	if whereSql != nil && len(where) != 0 { //条件查询
		query = query.Where(whereSql, where...)
	}

	if orderOrGroup.Group != "" { //分组
		query = query.Group(orderOrGroup.Group)
		if orderOrGroup.Having != "" { //分组筛选
			query = query.Having(orderOrGroup.Having)
		}
	}

	if orderOrGroup.Order != "" { //排序
		query = query.Order(orderOrGroup.Order)
	}

	//查询数量
	err = query.Count(&count).Error

	if err != nil { //查询数量失败
		return count, err
	}

	if paging.Page != 0 { //分页
		var pageSize int = 10
		if paging.PageSize != 0 {
			pageSize = paging.PageSize
		}
		query = query.Offset((paging.Page - 1) * pageSize).Limit(pageSize)
	}

	//查询数据列表
	err = query.Scan(list).Error
	return count, err
}

// TXQuery 开启事务的db
func (d *db) TXQuery() *gorm.DB {
	return d.Connect().Begin()
}

// Query 获取去数据库查询的db
func (d *db) Query() *gorm.DB {
	return d.Connect()
}

// NewDb 对外暴露
func NewDb(dbname string) *db {
	return &db{dbname}
}

// 自定义redis
type customRedis struct {
	db int
}

// Connect 动态切换redis库
func (r *customRedis) Connect() (client *redis.Client) {
	switch r.db {
	case 1:
		client = initialize.Library1RedisConnect()
	default:
		client = initialize.DefaultRedisConnect()
	}

	if client == nil {
		panic("redis库连接失败")
	}

	return client
}

// NewRedis 对外暴露
func NewRedis(db int) *customRedis {
	return &customRedis{db}
}
